package com.winner.es.controller;

import com.winner.es.controller.base.BaseController;
import com.winner.es.dao.EmployeeRepository;
import com.winner.es.exception.Result;
import com.winner.es.model.Employee;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.WildcardQueryBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.web.bind.annotation.*;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * CRUD
 */
@Slf4j
@RestController
@RequestMapping(value = "/employee")
public class EmployeeController extends BaseController {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    @Autowired
    private EmployeeRepository employeeRepository;

    @PostMapping
    public Result save(@RequestBody Employee employee) {
        employeeRepository.save(employee);
        return success();
    }

    @DeleteMapping("/{id}")
    public Result delete(@PathVariable("id") String id) {
        employeeRepository.deleteById(id);
        return success();
    }

    @PutMapping
    public Result update(@RequestBody Employee employee) {
        employeeRepository.save(employee); // id相同的保存就是修改 id入参在body里
        return success();
    }

    @GetMapping("/{id}")
    public Result get(@PathVariable("id") String id) {
        Optional<Employee> byId = employeeRepository.findById(id);
        if (byId.isPresent()) {
            return success(byId.get());
        }
        return success();
    }

    /**
     * 将/list/{pageSize}/{pageNo}/{keywords}/{fieldList} 的左边{替换为：  右边}直接删除，就可以在postman测此restfulApi了
     * localhost:8080/employee/list/:pageSize/:pageNo/:keywords/:fieldList
     * 分别在postman的Path Variables 位置依次填写如下参数
     * 10
     * 1
     * 华润置地 华润万家
     * name,businessUnitDescr,employeeId
     *
     * 指定多个分词字段进行全文检索
     * 输入的内容(可以空格隔开)  指定多个分词字段(name,businessUnitDescr,employeeId,email)
     */
    @GetMapping("/list/{pageSize}/{pageNo}/{keywords}/{fieldList}")
    public Page<Employee> list(@PathVariable Integer pageSize,
                                        @PathVariable Integer pageNo,
                                        @PathVariable String keywords,
                                        @PathVariable String[] fieldList) {
        //当然你可以链式编程一句写完 从创建基础查询器开始, 传入searchQuery即可  页码索引(从0开始 pageNo - 1)
        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withQuery(this.getQueryBuilders(Arrays.asList(fieldList), keywords))
                .withPageable(PageRequest.of(pageNo - 1, pageSize))
                .withSourceFilter(new FetchSourceFilter(new String[]{"id", "author"},null))//滤取结果 (只取 id 和 author字段)
               .withSort(SortBuilders.fieldSort("wordCount").order(SortOrder.DESC)) //排序 按发布时间的降序 和 价格的 升序进行排序 按name的降序排列会报错
                .build();
        Page<Employee> list = employeeRepository.search(searchQuery);
        return list;
    }

//      Spring Data 分页查询总是返回Page对象，Page对象提供了以下常用的方法：
//      int totalPages = list.getTotalPages();//总页数
//      List<Book> content = list.getContent();//所有的book对象
//      long totalElements = list.getTotalElements();//返回总记录数目
//      int pageNum = list.getPageable().getPageNumber();// 0
//      int pageSize = list.getPageable().getPageSize();// 10


    // 动态获取QueryBuilders    // 姓名 部门业务单位 不分词匹配   员工的 id  邮箱 手机号 模糊匹配
    private BoolQueryBuilder getQueryBuilders(List<String> fieldList, String keyword) {
        // 创建布尔查询器
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

        // term为精确匹配
        // QueryBuilders.termQuery("delFlag", 0);

        // 使用matchQuery进行查询时，搜索的词会被分词器分词，拆完后，再来匹配
        // QueryBuilders.multiMatchQuery(keyword);
        // QueryBuilders.matchQuery("12",keyword)

        // 使用matchPhraseQuery时，不会被分词器分词， 而是直接以一个短语的形式查询
        MatchPhraseQueryBuilder queryBuilderName = QueryBuilders.matchPhraseQuery("name", keyword);
        MatchPhraseQueryBuilder queryBuilderBusinessUnitDescr = QueryBuilders.matchPhraseQuery("businessUnitDescr", keyword);

        //模糊查询
        WildcardQueryBuilder queryBuilderEmplid = QueryBuilders.wildcardQuery("employeeId", "*" + keyword + "*");
        WildcardQueryBuilder queryBuilderMobilePhone = QueryBuilders.wildcardQuery("phone", "*" + keyword + "*");
        WildcardQueryBuilder queryBuilderEmail = QueryBuilders.wildcardQuery("email", "*" + keyword + "*");
        fieldList.forEach(field -> {
            switch (field) {
                case "name":
                    boolQueryBuilder.should(queryBuilderName); //  and not or   .must  .mustNot  .should(表示或者)
                    break;
                case "businessUnitDescr":   //name中含有 华润置地 或者businessUnitDescr含有 华润置地，相当于or
                    boolQueryBuilder.should(queryBuilderBusinessUnitDescr);
                    break;
                case "employeeId":
                    boolQueryBuilder.should(queryBuilderEmplid);
                    break;
                case "phone":
                    boolQueryBuilder.should(queryBuilderMobilePhone);
                    break;
                case "email":
                    boolQueryBuilder.should(queryBuilderEmail);
                    break;
                default:
                    break;
            }
        });
        return QueryBuilders.boolQuery().should(boolQueryBuilder);
    }
}
